package com.hopes.bizz.risk.control.support;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hopes.bizz.common.core.annotation.ExcelDictValidate;
import com.hopes.bizz.common.core.annotation.ExcelNotNull;
import com.hopes.bizz.common.core.util.StringUtils;
import com.hopes.bizz.risk.common.constant.RiskDicConstant;
import com.hopes.bizz.risk.common.constant.enums.RiskSysDictEnum;
import com.hopes.bizz.risk.control.entity.RiskMeasureTaskEntity;
import com.hopes.bizz.risk.control.entity.RiskUnitEntity;
import com.hopes.bizz.risk.control.entity.RiskUnitEventEntity;
import com.hopes.bizz.risk.control.mapper.RiskUnitEventMapper;
import com.hopes.bizz.risk.control.service.RiskUnitEventService;
import com.hopes.bizz.risk.control.service.RiskUnitService;
import com.hopes.bizz.risk.control.vo.*;
import com.hopes.boss.admin.api.entity.SysDictItem;
import com.hopes.boss.admin.api.resolver.DictLoader;
import com.hopes.boss.admin.api.resolver.DictResolver;
import com.hopes.boss.admin.api.resolver.EnumResolver;
import com.hopes.boss.admin.api.resolver.enums.AdminDictEnum;
import com.hopes.boss.admin.api.resolver.enums.SysDictEnum;
import com.hopes.boss.common.core.util.ClassUtils;
import com.hopes.boss.common.entity.ExcelDTO;
import com.hopes.boss.common.excel.vo.ErrorMessage;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 风险管控excel导入支撑类
 * @time 2023/7/31 13:03
 */
@Slf4j
@RequiredArgsConstructor
@Component("riskImportExcelSupport")
public class RiskImportExcelSupport {

    private final RiskUnitService riskUnitService;
    private final RiskUnitEventMapper riskUnitEventMapper;


    /**
     * 校验导入的数据
     * @param list     导入的数据
     * @param clazz    类
     * @return         结果集
     */
    public <T> List<T> restoreMergeData(List<T> list, Class<T> clazz) throws Exception {
        final List<T> importData = new ArrayList<>();
        for (T item : list) {
            final Field[] fields = clazz.getDeclaredFields();
            final Set<String> requiredNonNull = requiredNonNull(item, fields);
            if (CollectionUtil.isNotEmpty(requiredNonNull)) {
                if (CollectionUtil.isEmpty(importData)) {
                    continue;
                }
                final T element = importData.get(importData.size() - 1);
                if (null == element) {
                    continue;
                }
                for (Field field : fields) {
                    if (Modifier.isStatic(field.getModifiers())) {
                        continue;
                    }
                    field.setAccessible(true);
                    field.set(item, Optional.ofNullable(field.get(item)).orElse(field.get(element)));
                }
            }
            importData.add(item);
        }
        return importData;
    }

    /**
     * 验证非空字典
     * @param item     对象
     * @param fields   所属属性
     * @return         验证结果
     */
    private <T> Set<String> requiredNonNull(T item, Field[] fields) {
        final HashSet<String> result = new HashSet<>();
        for (Field field : fields) {
            final ExcelNotNull annotation = field.getAnnotation(ExcelNotNull.class);
            if (null == annotation) {
                continue;
            }
            try {
                final Object propertyValue = ClassUtils.getPropertyValue(item, field.getName());
                if (null == propertyValue || propertyValue.toString().trim().equals("")) {
                    result.add(annotation.message());
                }
            }catch (Exception e) {
                log.error("class: {}, field: {}, get value error !", item.getClass().getName(), field.getName());
            }
        }
        return result;
    }

    /**
     * 校验excel中字典数据
     * @param bindingResult   错误数据
     * @param importDataList  excel数据
     * @param clazz           类
     * @return                结果集
     */
    @SuppressWarnings("unchecked")
    public <T> List<ErrorMessage> validateDictData(BindingResult bindingResult, List<T> importDataList, Class<T> clazz) throws Exception {
        final List<ErrorMessage> errorMessageList = Optional.ofNullable((List<ErrorMessage>) bindingResult.getTarget()).orElseGet(ArrayList::new);

        // 字典数据 map
        final Map<String, List<SysDictItem>> enumResolverMap = new HashMap<>();
        final List<Field> dictFieldList = Arrays.stream(clazz.getDeclaredFields()).filter(field -> ObjectUtil.isNotNull(field.getAnnotation(ExcelDictValidate.class))).collect(Collectors.toList());
        // 字典栏位数据
        for (Field field : dictFieldList) {
            final EnumResolver<?> enumResolver = DictLoader.getInstance().getEnumResolverByType(field.getAnnotation(ExcelDictValidate.class).enumResolver());
            enumResolverMap.put(enumResolver.getType(), DictResolver.getItemsByType(enumResolver));
        }
        // 校验数据
        for (T item : importDataList) {
            Set<String> errorMsg = new HashSet<>();
            for (Field field : dictFieldList) {
                final ExcelDictValidate annotation = field.getAnnotation(ExcelDictValidate.class);
                final String enumResolver = annotation.enumResolver();
                final List<SysDictItem> sysDictItemList = enumResolverMap.get(enumResolver);
                if (CollectionUtil.isEmpty(sysDictItemList)) {
                    continue;
                }
                final Object propertyValue = ClassUtils.getPropertyValue(item, field.getName());
                if (ObjectUtil.isNull(propertyValue)) {
                    continue;
                }
                // 校验数据是否已经存在
                validateDataIsExist(errorMsg, annotation, field, sysDictItemList, propertyValue);
            }
            if (!CollUtil.isEmpty(errorMsg)) {
                // 数据不合法情况
                errorMessageList.add(new ErrorMessage(((ExcelDTO)item).getLineNum(), errorMsg));
            }
        }
        return errorMessageList;
    }

    /**
     * 校验数据是否存在，如字典数据项是否存在
     * @param errorMsg         错误信息
     * @param annotation       注解
     * @param field            字典
     * @param sysDictItemList  字典数据
     * @param propertyValue    字段值
     */
    private <T> void validateDataIsExist(Set<String> errorMsg, ExcelDictValidate annotation, Field field, List<SysDictItem> sysDictItemList, Object propertyValue) {
        if (!annotation.multiple()) {
            final boolean b = sysDictItemList.stream().anyMatch(e -> propertyValue.toString().equals(e.getName()));
            if (!b) {
                final String[] value = field.getAnnotation(ExcelProperty.class).value();
                final String column = Arrays.stream(value).skip(value.length - 1).findFirst().orElse("default column");
                errorMsg.add( "【" + column  + "】" + propertyValue + "数据无法解析，请确认！");
            }
        } else {
            final List<String> split = StrUtil.split(propertyValue.toString(), StrUtil.COMMA);
            final List<SysDictItem> collect = sysDictItemList.stream().filter(e ->
                    ObjectUtil.isNotNull(e.getName())).filter(e -> split.stream().anyMatch(m -> e.getName().equals(m))).collect(Collectors.toList());
            if (collect.size() < split.size()) {
                final String[] value = field.getAnnotation(ExcelProperty.class).value();
                final String column = Arrays.stream(value).skip(value.length - 1).findFirst().orElse("default column");
                errorMsg.add( "【" + column  + "】" + propertyValue + "数据中存在无法解析的数据，请确认！");
            }
        }
    }


    /**
     * 风险事件集合
     * @param identifyExcelVOList 导入的辨识管控数据
     * @param riskUnitId          风险单元Id
     * @return                    风险事件集合
     */
    public List<RiskUnitEventVO> buildRiskIdentifyImport(List<RiskIdentifyExcelVO> identifyExcelVOList, Long riskUnitId) {
        final List<RiskUnitEventVO> resultList = new ArrayList<>();
        final Map<String, Map<String, SysDictItem>> labelValueMap = importLabelValueMap();
        // 1、根据风险事件名称分组
        final LinkedHashSet<String> eventNameTreeSet = identifyExcelVOList.parallelStream().map(RiskIdentifyExcelVO::getEventName).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
        final Map<String, List<RiskIdentifyExcelVO>> listMap = identifyExcelVOList.parallelStream().filter(e -> null != e.getEventName()).collect(Collectors.groupingBy(RiskIdentifyExcelVO::getEventName));
        // 2、遍历风险事件
        for (String eventName : eventNameTreeSet) {
            final List<RiskIdentifyExcelVO> collect = listMap.get(eventName).stream().sorted(Comparator.comparing(e -> Integer.valueOf(e.getIndex()))).collect(Collectors.toList());
            final RiskUnitEventVO eventVO = buildRiskUnitEventVo(labelValueMap, collect, riskUnitId);
            // 3、根据管控措施描述分组
            eventVO.setRiskControlMeasureList(buildRiskControlMeasureVoList(labelValueMap, riskUnitId, collect));
            resultList.add(eventVO);
        }
        return resultList;
    }

    /**
     * 构建风险事件
     * @param labelValueMap  字典集合
     * @param collect        导入的数据
     * @param riskUnitId     参数
     * @return               结果集
     */
    private RiskUnitEventVO buildRiskUnitEventVo(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskIdentifyExcelVO> collect, Long riskUnitId) {
        final Optional<RiskIdentifyExcelVO> riskIdentifyImport = Optional.ofNullable(collect.get(0));
        final Map<String, SysDictItem> riskLevelMap = labelValueMap.get("riskLevelMap");  //风险等级

        final RiskUnitEventVO eventVO = new RiskUnitEventVO();
        eventVO.setRiskUnitId(riskUnitId);
        eventVO.setJobStep(riskIdentifyImport.map(RiskIdentifyExcelVO::getJobStep).orElse(null));
        eventVO.setRiskDesc(riskIdentifyImport.map(RiskIdentifyExcelVO::getRiskDesc).orElse(null));
        eventVO.setEventName(riskIdentifyImport.map(RiskIdentifyExcelVO::getEventName).orElse(null));
        eventVO.setAfterRiskDesc(riskIdentifyImport.map(RiskIdentifyExcelVO::getAfterRiskDesc).orElse(null));
        eventVO.setMajorConsequenceDesc(riskIdentifyImport.map(RiskIdentifyExcelVO::getMajorConsequenceDesc).orElse(null));
        eventVO.setRiskLevel(getLabelValueByLabel(riskIdentifyImport.map(RiskIdentifyExcelVO::getRiskLevelStr).orElse(null), riskLevelMap, Integer::valueOf));
        eventVO.setAfterRiskLevel(getLabelValueByLabel(riskIdentifyImport.map(RiskIdentifyExcelVO::getAfterRiskLevelStr).orElse(null), riskLevelMap, Integer::valueOf));
        return eventVO;
    }

    /**
     * 构建风险辨识管控措施集合
     * @param labelValueMap  字典集合
     * @param riskUnitId     风险单元Id
     * @param list           导入的数据
     * @return               管控措施集合
     */
    private List<RiskControlMeasureVO> buildRiskControlMeasureVoList(Map<String, Map<String, SysDictItem>> labelValueMap, Long riskUnitId, List<RiskIdentifyExcelVO> list) {
        final List<RiskControlMeasureVO> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(list)) {
            return result;
        }
        final Map<String, SysDictItem> classifyMap = labelValueMap.get("classifyMap");   // 措施分类
        final Map<String, SysDictItem> controlLevelMap = labelValueMap.get("controlLevelMap"); // 管控层级

        // 1、遍历管控措施数据
        final LinkedHashSet<String> controlMeasureSet = list.parallelStream().map(this::getControlMeasureKey).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
        final Map<String, List<RiskIdentifyExcelVO>> controlMeasureMap = list.parallelStream().filter(e -> null != this.getControlMeasureKey(e)).collect(Collectors.groupingBy(this::getControlMeasureKey));
        // 2、遍历管控措施数据
        for (String measureDesc : controlMeasureSet) {
            final List<RiskIdentifyExcelVO> collect = controlMeasureMap.get(measureDesc).stream().sorted(Comparator.comparing(e -> Integer.valueOf(e.getIndex()))).collect(Collectors.toList());
            final Optional<RiskIdentifyExcelVO> controlOptional = Optional.ofNullable(collect.get(0));

            final RiskControlMeasureVO controlMeasureVO = new RiskControlMeasureVO();
            controlMeasureVO.setRiskUnitId(riskUnitId);
            controlMeasureVO.setControlType(RiskDicConstant.RISK_CONTROL_MEASURE_CONTROL_TYPE_2);
            controlMeasureVO.setLawDesc(controlOptional.map(RiskIdentifyExcelVO::getLawDesc).orElse(null));
            controlMeasureVO.setClassify3(controlOptional.map(RiskIdentifyExcelVO::getClassify3).orElse(null));
            controlMeasureVO.setCheckContent(controlOptional.map(RiskIdentifyExcelVO::getCheckContent).orElse(null));
            controlMeasureVO.setRiskMeasureDesc(controlOptional.map(RiskIdentifyExcelVO::getRiskMeasureDesc).orElse(null));
            controlMeasureVO.setClassify1(getLabelValueByLabel(controlOptional.map(RiskIdentifyExcelVO::getClassify1Str).orElse(null), classifyMap));
            controlMeasureVO.setClassify2(getLabelValueByLabel(controlOptional.map(RiskIdentifyExcelVO::getClassify2Str).orElse(null), classifyMap));
            controlMeasureVO.setControlLevel(getLabelValueByLabel(controlOptional.map(RiskIdentifyExcelVO::getControlLevelStr).orElse(null), controlLevelMap, Integer::valueOf));

            // 任务排查内容
            final List<RiskMeasureTaskConfigVO> measureTaskConfigVOList = new ArrayList<>();
            final LinkedHashSet<String> taskCheckContentTreeSet = collect.stream().map(RiskIdentifyExcelVO::getTaskCheckContent).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
            final Map<String, List<RiskIdentifyExcelVO>> taskCheckContentMap = collect.parallelStream().filter(e -> null != e.getTaskCheckContent()).collect(Collectors.groupingBy(RiskIdentifyExcelVO::getTaskCheckContent));
            for (String taskCheckContent : taskCheckContentTreeSet) {
                final RiskMeasureTaskConfigVO taskConfigVO = new RiskMeasureTaskConfigVO();
                taskConfigVO.setRiskUnitId(riskUnitId);
                taskConfigVO.setCheckContent(taskCheckContent);
                final List<RiskIdentifyExcelVO> taskList = taskCheckContentMap.get(taskCheckContent).stream().sorted(Comparator.comparing(e -> Integer.valueOf(e.getIndex()))).collect(Collectors.toList());
                taskConfigVO.setRiskMeasureTaskList(buildRiskIdentifyTask(labelValueMap, taskList));
                measureTaskConfigVOList.add(taskConfigVO);
            }
            controlMeasureVO.setRiskMeasureTaskConfigList(measureTaskConfigVOList);

            result.add(controlMeasureVO);
        }
        return result;
    }

    private List<RiskMeasureTaskEntity> buildRiskIdentifyTask(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskIdentifyExcelVO> importList) {
        final List<RiskMeasureTaskEntity> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(importList)) {
            return result;
        }

        final Map<String, SysDictItem> controlLevelMap = labelValueMap.get("controlLevelMap"); // 管控层级
        final Map<String, SysDictItem> checkCycleTypeMap = labelValueMap.get("checkCycleTypeMap"); // 排查任务周期
        final Map<String, SysDictItem> responsibleUserMap = labelValueMap.get("responsibleUserMap"); // 排查任务责任人

        for (RiskIdentifyExcelVO identifyExcelVO : importList) {
            final RiskMeasureTaskEntity measureTaskEntity = new RiskMeasureTaskEntity();
            final Optional<RiskIdentifyExcelVO> importOptional = Optional.ofNullable(identifyExcelVO);
            measureTaskEntity.setWorkType(RiskDicConstant.RISK_WORK_TYPE_0);
            measureTaskEntity.setWorkDayType(RiskDicConstant.RISK_WORK_DAY_TYPE_0);
            measureTaskEntity.setWorkEndTime(RiskDicConstant.RISK_MEASURE_TASK_WORK_END_TIME);
            measureTaskEntity.setWorkStartTime(RiskDicConstant.RISK_MEASURE_TASK_WORK_START_TIME);
            measureTaskEntity.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_CONFIG_STATUS_NOT_USE);
            measureTaskEntity.setCheckCycle(importOptional.map(RiskIdentifyExcelVO::getCheckCycle).map(Integer::valueOf).orElse(null));
            measureTaskEntity.setCheckCycleType(getLabelValueByLabel(importOptional.map(RiskIdentifyExcelVO::getCheckCycleTypeStr).orElse(null), checkCycleTypeMap));
            //measureTaskEntity.setResponsibleUserIds(getLabelValueByLabel(importOptional.map(RiskIdentifyExcelVO::getResponsibleUserIdsStr).orElse(null), responsibleUserMap));
            measureTaskEntity.setControlLevel(getLabelValueByLabel(importOptional.map(RiskIdentifyExcelVO::getControlLevelStr).orElse(null), controlLevelMap, Integer::valueOf));
            result.add(measureTaskEntity);
        }
        return result;
    }




    /**
     * 导入字典Map
     * @return 字典Map
     */
    public Map<String, Map<String, SysDictItem>> importLabelValueMap() {
        /* 风险对象 - 对象类型 */
        final Map<String, SysDictItem> objectTypeMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_object_type).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));
        /* 是否 */
        final Map<String, SysDictItem> trueOrFalseMap = DictResolver.getItemsByType(SysDictEnum.yes_no_type).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));
        /* 管控层级（公司级、车间级、班组级、岗位级） */
        final Map<String, SysDictItem> controlLevelMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_control_level).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));
        /* 责任部门 */
        final Map<String, SysDictItem> departmentMap = DictResolver.getItemsByType(AdminDictEnum.sys_dept).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e, (key1, key2) -> key2));
        /* 责任人 */
        final Map<String, SysDictItem> responsibleUserMap = DictResolver.getItemsByType(AdminDictEnum.sys_user).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e, (key1, key2) -> key2));

        /* 风险单元 - 单元类型*/
        final Map<String, SysDictItem> unitTypeMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_unit_type).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));
        /* 风险单元 - 评估方法 */
        final Map<String, SysDictItem> evaluateMethodMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_evaluate_method).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));

        /* 风险事件 - 固有风险等级&&现状风险等级 */
        final Map<String, SysDictItem> riskLevelMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_level).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));

        /* 管控措施 - 措施分类 */
        final Map<String, SysDictItem> classifyMap = DictResolver.getItemsByType(RiskSysDictEnum.risk_control_classify).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));
        /* 隐患排查任务 - 检查周期类型 */
        final Map<String, SysDictItem> checkCycleTypeMap = DictResolver.getItemsByType(RiskSysDictEnum.check_cycle_type).stream().collect(Collectors.toMap(SysDictItem::getName, e -> e));

        return new HashMap<String, Map<String, SysDictItem>>() {
            private static final long serialVersionUID = -4770473849382053319L;

            {
                put("classifyMap", classifyMap);
                put("unitTypeMap", unitTypeMap);
                put("riskLevelMap", riskLevelMap);
                put("objectTypeMap", objectTypeMap);
                put("departmentMap", departmentMap);
                put("trueOrFalseMap", trueOrFalseMap);
                put("controlLevelMap", controlLevelMap);
                put("checkCycleTypeMap", checkCycleTypeMap);
                put("evaluateMethodMap", evaluateMethodMap);
                put("responsibleUserMap", responsibleUserMap);
            }
        };
    }


    /**
     * 构建管控措施
     *
     * @param labelValueMap 字典集合
     * @param collect       导入的数据
     * @return 管控措施
     */
    public RiskControlMeasureVO buildRiskControlMeasure(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> collect) {
        final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(collect.get(0));

        final Map<String, SysDictItem> classifyMap = labelValueMap.get("classifyMap");   // 措施分类
        final Map<String, SysDictItem> controlLevelMap = labelValueMap.get("controlLevelMap");  // 管控层级

        final RiskControlMeasureVO controlMeasure = new RiskControlMeasureVO();
        controlMeasure.setControlType(RiskDicConstant.RISK_CONTROL_MEASURE_CONTROL_TYPE_2);
        controlMeasure.setLawDesc(detailedImport.map(RiskDetailExcelVO::getLawDesc).orElse(null));
        controlMeasure.setClassify3(detailedImport.map(RiskDetailExcelVO::getClassify3).orElse(null));
        controlMeasure.setCheckContent(detailedImport.map(RiskDetailExcelVO::getCheckContent).orElse(null));
        controlMeasure.setRiskMeasureDesc(detailedImport.map(RiskDetailExcelVO::getRiskMeasureDesc).orElse(null));
        controlMeasure.setClassify1(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getClassify1Str).orElse(null), classifyMap));
        controlMeasure.setClassify2(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getClassify2Str).orElse(null), classifyMap));
        controlMeasure.setControlLevel(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getControlLevelStr).orElse(null), controlLevelMap, Integer::valueOf));
        return controlMeasure;
    }

    /**
     * 构建风险分析对象
     *
     * @param labelValueMap 字典映射
     * @param collect       导入的数据
     * @return 风险分析对象
     */
    public RiskObjectVO buildRiskObject(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> collect) {
        final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(collect.get(0));

        final Map<String, SysDictItem> objectTypeMap = labelValueMap.get("objectTypeMap");  // 对象类型
        final Map<String, SysDictItem> departmentMap = labelValueMap.get("departmentMap");  // 责任部门
        final Map<String, SysDictItem> trueOrFalseMap = labelValueMap.get("trueOrFalseMap");  // 是否
        final Map<String, SysDictItem> responsibleUserMap = labelValueMap.get("responsibleUserMap");  // 责任人
        final RiskObjectVO object = new RiskObjectVO();
        object.setReportDataFlag(false);
        object.setHazardName(detailedImport.map(RiskDetailExcelVO::getObjectHazardName).orElse(null));
        object.setHazardCode(detailedImport.map(RiskDetailExcelVO::getObjectHazardCode).orElse(null));
        object.setDeptId(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getObjectDeptIdStr).orElse(null), departmentMap));
        object.setPrincipal(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getObjectPrincipalStr).orElse(null), responsibleUserMap));
        object.setHazardType(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getObjectHazardTypeStr).orElse(null), objectTypeMap, Integer::valueOf));
        object.setHazardSourceFlag(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getHazardSourceFlagStr).orElse(String.valueOf(false)), trueOrFalseMap, Boolean::valueOf));

        return object;
    }

    /**
     * 构建风险分析事件
     *
     * @param labelValueMap 字典映射
     * @param collect       导入的数据
     * @return 风险分析事件
     */
    public RiskUnitEventVO buildRiskUnitEvent(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> collect) {
        final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(collect.get(0));

        final Map<String, SysDictItem> riskLevelMap = labelValueMap.get("riskLevelMap");  // 风险等级

        final RiskUnitEventVO event = new RiskUnitEventVO();
        event.setJobStep(detailedImport.map(RiskDetailExcelVO::getJobStep).orElse(null));
        event.setRiskDesc(detailedImport.map(RiskDetailExcelVO::getRiskDesc).orElse(null));
        event.setEventName(detailedImport.map(RiskDetailExcelVO::getEventName).orElse(null));
        event.setAfterRiskDesc(detailedImport.map(RiskDetailExcelVO::getAfterRiskDesc).orElse(null));
        event.setMajorConsequenceDesc(detailedImport.map(RiskDetailExcelVO::getMajorConsequenceDesc).orElse(null));
        event.setRiskLevel(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getRiskLevelStr).orElse(null), riskLevelMap, Integer::valueOf));
        event.setAfterRiskLevel(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getAfterRiskLevelStr).orElse(null), riskLevelMap, Integer::valueOf));
        // 风险单元
        event.setRiskUnit(buildRiskUnit(labelValueMap, collect));
        return event;
    }

    /**
     * 构建风险分析单元
     *
     * @param labelValueMap 字典映射
     * @param collect       导入的数据
     * @return 风险分析单元
     */
    private RiskUnitVO buildRiskUnit(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> collect) {
        final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(collect.get(0));

        final Map<String, SysDictItem> unitTypeMap = labelValueMap.get("unitTypeMap");  // 单元类型
        final Map<String, SysDictItem> departmentMap = labelValueMap.get("departmentMap");  // 责任部门
        final Map<String, SysDictItem> evaluateMethodMap = labelValueMap.get("evaluateMethodMap"); // 评估方法
        final Map<String, SysDictItem> responsibleUserMap = labelValueMap.get("responsibleUserMap");  // 责任人
        final RiskUnitVO riskUnit = new RiskUnitVO();
        riskUnit.setReportDataFlag(false);
        riskUnit.setRiskName(detailedImport.map(RiskDetailExcelVO::getUnitName).orElse(null));
        riskUnit.setPrincipal(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getUnitPrincipalStr).orElse(null), responsibleUserMap));
        riskUnit.setEvaluateMethod(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getEvaluateMethodStr).orElse(null), evaluateMethodMap));
        riskUnit.setRiskUnitType(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getUnitTypeStr).orElse(null), unitTypeMap, Integer::valueOf));

        return riskUnit;
    }


    /**
     * 校验导入数据中风险描述是否符合所属单元的辨识方法
     * @param bindingResult   错误信息
     * @param riskUnitId      风险单元Id
     * @param importList      导入的数据
     * @return                结果集
     */
    @SuppressWarnings("unchecked")
    public List<ErrorMessage> validateEvaluateMethodAndDesc(BindingResult bindingResult, Long riskUnitId, List<RiskIdentifyExcelVO> importList) {
        final List<ErrorMessage> errorMessageList = Optional.ofNullable((List<ErrorMessage>) bindingResult.getTarget()).orElseGet(ArrayList::new);

        final RiskUnitEntity riskUnitEntity = riskUnitService.getById(riskUnitId);
        if (null == riskUnitEntity || StringUtils.isEmpty(riskUnitEntity.getEvaluateMethod())) {
            final Set<String> errorMsg = new HashSet<>();
            errorMsg.add("风险单元或者风险单元中评估方法不可为空！");
            errorMessageList.add(new ErrorMessage(1L, errorMsg));
        } else {
            // 1、评估方法
            for (RiskIdentifyExcelVO identifyExcelVO : importList) {
                validateEvaluateMethodAndDesc(errorMessageList, identifyExcelVO.getRiskDesc(), identifyExcelVO.getAfterRiskDesc(), identifyExcelVO.getLineNum(), riskUnitEntity.getEvaluateMethod());
            }
        }
        return errorMessageList;
    }

    /**
     * 校验风险事件是否已存在
     * @param bindingResult  错误信息
     * @param riskUnitId     单元Id
     * @param importList     导入的数据
     * @return                    结果
     */
    @SuppressWarnings("unchecked")
    public List<ErrorMessage> validateEventIsExist(BindingResult bindingResult, Long riskUnitId, List<RiskIdentifyExcelVO> importList) {
        final List<ErrorMessage> errorMessageList = Optional.ofNullable((List<ErrorMessage>) bindingResult.getTarget()).orElseGet(ArrayList::new);
        final List<RiskUnitEventEntity> riskUnitEventList = riskUnitEventMapper.selectList(
                Wrappers.<RiskUnitEventEntity>lambdaQuery().eq(RiskUnitEventEntity::getRiskUnitId, riskUnitId));
        if (CollUtil.isEmpty(riskUnitEventList)) {
            return errorMessageList;
        }
        final Set<String> eventNameTreeSet = riskUnitEventList.parallelStream()
                .map(RiskUnitEventEntity::getEventName).filter(Objects::nonNull).collect(Collectors.toCollection(LinkedHashSet::new));
        if (CollUtil.isEmpty(eventNameTreeSet)) {
            return errorMessageList;
        }
        for (RiskIdentifyExcelVO identifyExcelVO : importList) {
            validateEventIsExist(errorMessageList, eventNameTreeSet, identifyExcelVO.getEventName(), identifyExcelVO.getLineNum());
        }
        return errorMessageList;
    }

    private void validateEventIsExist(List<ErrorMessage> errorMessageList, Set<String> eventNameTreeSet, String eventName, Long lineNum) {
        final Set<String> errorMsg = new HashSet<>();
        if (StrUtil.isNotEmpty(eventName) && eventNameTreeSet.contains(eventName)) {
            errorMsg.add("【" + eventName + "】" + "风险事件已存在，请确认");
        }
        if (!CollUtil.isEmpty(errorMsg)) {
            errorMessageList.add(new ErrorMessage(lineNum, errorMsg));
        }
    }

    @SuppressWarnings("unchecked")
    public List<ErrorMessage> validateEvaluateMethodAndDesc(BindingResult bindingResult, List<RiskDetailExcelVO> detailExcelVOList) {
        final List<ErrorMessage> errorMessageList = Optional.ofNullable((List<ErrorMessage>) bindingResult.getTarget()).orElseGet(ArrayList::new);

        for (RiskDetailExcelVO riskDetailExcelVO : detailExcelVOList) {
            validateEvaluateMethodAndDesc(errorMessageList, riskDetailExcelVO.getRiskDesc(), riskDetailExcelVO.getAfterRiskDesc(), riskDetailExcelVO.getLineNum(), riskDetailExcelVO.getEvaluateMethodStr());
        }
        return errorMessageList;
    }

    private void validateEvaluateMethodAndDesc(List<ErrorMessage> errorMessageList, String riskDesc, String afterRiskDesc, Long lineNum, String evaluateMethod) {
        final Set<String> errorMsg = new HashSet<>();
        if (StringUtil.isNotEmpty(riskDesc)) {
            final boolean b = StringUtils.containsAllCharFromStr(riskDesc, evaluateMethod);
            if (!b) {
                errorMsg.add("固有风险描述不符合评估方法，请确认");
            }
        }
        if (StringUtil.isNotEmpty(afterRiskDesc)) {
            final boolean b = StringUtils.containsAllCharFromStr(afterRiskDesc, evaluateMethod);
            if (!b) {
                errorMsg.add("现状风险描述不符合评估方法，请确认");
            }
        }
        if (!CollUtil.isEmpty(errorMsg)) {
            // 数据不合法情况
            errorMessageList.add(new ErrorMessage(lineNum, errorMsg));
        }
    }

    /**
     * 构建管控措施
     *
     * @param detailExcelVOList 数据
     * @return 风险辨识清单数据
     */
    public List<RiskControlMeasureVO> buildRiskControlMeasureList(List<RiskDetailExcelVO> detailExcelVOList) {
        if (CollectionUtil.isEmpty(detailExcelVOList)) {
            return new ArrayList<>();
        }
        final List<RiskControlMeasureVO> result = new ArrayList<>();
        final Map<String, Map<String, SysDictItem>> labelValueMap = this.importLabelValueMap();
        // 1、根据管控措施描述分组，使用LinkedHashSet保证顺序
        final LinkedHashSet<String> controlSet = detailExcelVOList.parallelStream().map(this::getControlMeasureKey).filter(StrUtil::isNotEmpty).collect(Collectors.toCollection(LinkedHashSet::new));
        final Map<String, List<RiskDetailExcelVO>> controlListMap = detailExcelVOList.parallelStream().filter(e -> StringUtil.isNotEmpty(getControlMeasureKey(e))).collect(Collectors.groupingBy(this::getControlMeasureKey));
        for (String item : controlSet) {
            final List<RiskDetailExcelVO> collect = controlListMap.get(item).parallelStream().sorted(Comparator.comparing(e -> Integer.valueOf(e.getIndex()))).collect(Collectors.toList());
            final RiskControlMeasureVO controlMeasureVO = buildRiskControlMeasure(labelValueMap, collect);
            // 风险对象
            controlMeasureVO.setRiskObject(buildRiskObject(labelValueMap, collect));
            // 风险事件
            controlMeasureVO.setRiskUnitEvent(buildRiskUnitEvent(labelValueMap, collect));
            controlMeasureVO.setRiskMeasureTaskConfigList(buildRiskMeasureTaskConfigList(labelValueMap, collect));

            result.add(controlMeasureVO);
        }
        return result;
    }

    private String getControlMeasureKey(RiskIdentifyExcelVO riskIdentifyExcelVO) {
        if (Objects.isNull(riskIdentifyExcelVO)) {
            return null;
        }
        return riskIdentifyExcelVO.getEventName() + riskIdentifyExcelVO.getRiskMeasureDesc();
    }

    /**
     * 获取管控措施 Key
     * @param riskDetailExcelVO 导入对象
     * @return   key(对象名称、单元名称、时间名称、管控措施描述)
     */
    private String getControlMeasureKey(RiskDetailExcelVO riskDetailExcelVO) {
        if (Objects.isNull(riskDetailExcelVO)) {
            return null;
        }
        return riskDetailExcelVO.getObjectHazardName() + riskDetailExcelVO.getUnitName() + riskDetailExcelVO.getEventName() + riskDetailExcelVO.getRiskMeasureDesc();
    }


    /**
     * 构建管控措施 -》 隐患排查内容及排查任务集合
     *
     * @param labelValueMap 字典集合
     * @param list          导入的数据
     * @return 排查内容集合
     */
    public List<RiskMeasureTaskConfigVO> buildRiskMeasureTaskConfigList(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> list) {
        final List<RiskMeasureTaskConfigVO> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(list)) {
            return result;
        }
        // 数据根据排查内容分组，LinkedHashSet用于保证顺序
        final LinkedHashSet<String> taskCheckContentSet = list.parallelStream().map(RiskDetailExcelVO::getTaskCheckContent).collect(Collectors.toCollection(LinkedHashSet::new));
        final Map<String, List<RiskDetailExcelVO>> taskCheckContentListMap = list.parallelStream().filter(e -> StringUtil.isNotEmpty(e.getTaskCheckContent())).collect(Collectors.groupingBy(RiskDetailExcelVO::getTaskCheckContent));
        for (String taskCheckContent : taskCheckContentSet) {
            final List<RiskDetailExcelVO> collect = taskCheckContentListMap.get(taskCheckContent).parallelStream().sorted(Comparator.comparing(e -> Integer.valueOf(e.getIndex()))).collect(Collectors.toList());

            final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(collect.get(0));
            final RiskMeasureTaskConfigVO taskConfig = new RiskMeasureTaskConfigVO();
            taskConfig.setCheckContent(detailedImport.map(RiskDetailExcelVO::getTaskCheckContent).orElse(null));
            taskConfig.setRiskMeasureTaskList(buildRiskMeasureTaskList(labelValueMap, collect));
            result.add(taskConfig);
        }
        return result;
    }

    /**
     * 后见隐患排查任务集合
     *
     * @param labelValueMap 字典集合
     * @param list          导入的数据
     * @return 排查任务集合
     */
    private List<RiskMeasureTaskEntity> buildRiskMeasureTaskList(Map<String, Map<String, SysDictItem>> labelValueMap, List<RiskDetailExcelVO> list) {
        final List<RiskMeasureTaskEntity> result = new ArrayList<>();
        if (CollectionUtil.isEmpty(list)) {
            return result;
        }
        final Map<String, SysDictItem> controlLevelMap = labelValueMap.get("controlLevelMap");  // 管控层级
        final Map<String, SysDictItem> checkCycleTypeMap = labelValueMap.get("checkCycleTypeMap");  // 排查任务周期
        final Map<String, SysDictItem> responsibleUserMap = labelValueMap.get("responsibleUserMap");  // 排查任务责任人

        for (RiskDetailExcelVO riskDetailExcelVO : list) {
            final Optional<RiskDetailExcelVO> detailedImport = Optional.ofNullable(riskDetailExcelVO);

            final RiskMeasureTaskEntity measureTask = new RiskMeasureTaskEntity();
            measureTask.setWorkType(RiskDicConstant.RISK_WORK_TYPE_0);
            measureTask.setWorkDayType(RiskDicConstant.RISK_WORK_DAY_TYPE_0);
            measureTask.setWorkEndTime(RiskDicConstant.RISK_MEASURE_TASK_WORK_END_TIME);
            measureTask.setWorkStartTime(RiskDicConstant.RISK_MEASURE_TASK_WORK_START_TIME);
            measureTask.setTaskStatus(RiskDicConstant.HIDDEN_CHECK_CONFIG_STATUS_NOT_USE);
            measureTask.setCheckCycle(detailedImport.map(RiskDetailExcelVO::getCheckCycle).map(Integer::valueOf).orElse(null));
            measureTask.setCheckCycleType(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getCheckCycleTypeStr).orElse(null), checkCycleTypeMap));
            //measureTask.setResponsibleUserIds(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getResponsibleUserIdsStr).orElse(null), responsibleUserMap));
            measureTask.setControlLevel(getLabelValueByLabel(detailedImport.map(RiskDetailExcelVO::getTaskControlLevelStr).orElse(null), controlLevelMap, Integer::valueOf));
            result.add(measureTask);
        }
        return result;
    }

    /**
     * 根据label获取value数据
     *
     * @param label         标签
     * @param labelValueMap 字典对象map
     * @return 结果
     */
    private String getLabelValueByLabel(String label, Map<String, SysDictItem> labelValueMap) {
        if (StringUtil.isEmpty(label) || MapUtil.isEmpty(labelValueMap)) {
            return null;
        }
        if (label.contains(",")) {
            final StringBuilder sb = new StringBuilder();
            for (String item : label.split(",")) {
                if (!labelValueMap.containsKey(item)) {
                    continue;
                }
                sb.append(",").append(labelValueMap.get(item).getCode());
            }
            if (sb.length() > 0) {
                return sb.substring(1);
            }
        }
        return Optional.ofNullable(labelValueMap.get(label)).map(SysDictItem::getCode).orElse(null);
    }

    /**
     * 根据label获取value数据， value需要转其他类型
     *
     * @param label         标签
     * @param labelValueMap 字段对象map
     * @param mapper        映射
     * @return 结果
     */
    private <T> T getLabelValueByLabel(String label, Map<String, SysDictItem> labelValueMap, Function<String, T> mapper) {
        if (StringUtil.isEmpty(label) || MapUtil.isEmpty(labelValueMap) || null == mapper) {
            return null;
        }
        return Optional.ofNullable(labelValueMap.get(label)).map(SysDictItem::getCode).map(mapper).orElse(null);
    }


}
